package com.example.demo.controller;

import cn.hutool.core.util.IdUtil;
import cn.hutool.json.JSONUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayDataDataserviceBillDownloadurlQueryModel;
import com.alipay.api.domain.AlipayTradeQueryModel;
import com.alipay.api.domain.AlipayTradeRefundModel;
import com.alipay.api.request.*;
import com.alipay.api.response.*;
import com.example.demo.entity.AlipayBean;
import com.example.demo.entity.AlipayProperties;
import com.example.demo.service.Alipay;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;


@RestController
@RequestMapping("/alipay")
public class AliPayController {

    private static final Log log = LogFactory.get();

    private final String FAST_INSTANT_TRADE_PAY = "FAST_INSTANT_TRADE_PAY";

    @Autowired
    AlipayProperties alipayProperties;
    // 定时任务线程池
    private static ScheduledExecutorService scheduledExecutorService;


    @Autowired
    Alipay alipay;

    @PostMapping(value = "/pay")
    public String alipay(AlipayBean alipayBean) throws AlipayApiException {
        return alipay.pay(alipayBean);
    }

    @PostMapping(value = "success")
    public String success() {
        return "success";
    }

    public AlipayClient getClient() {
        String serverUrl = alipayProperties.getGatewayUrl();
        String appId = alipayProperties.getApp_id();
        String privateKey = alipayProperties.getPrivateKey();
        String format = "json";
        String charset = alipayProperties.getCharset();
        String alipayPublicKey = alipayProperties.getPublicKey();
        String signType = alipayProperties.getSign_type();
        AlipayClient alipayClient = new DefaultAlipayClient(serverUrl, appId, privateKey, format, charset, alipayPublicKey, signType);
        return alipayClient;
    }

    /**
     * 电脑下单支付
     *
     * @param alipayBean 商品信息
     */
    @PostMapping(value = "/testpay")
    public String testpay(@RequestBody AlipayBean alipayBean) throws AlipayApiException {
        scheduledExecutorService = Executors.newScheduledThreadPool(10);
        // 订单号
        String out_trade_no = IdUtil.simpleUUID();
        alipayBean.setOut_trade_no(out_trade_no);
        alipayBean.setProduct_code(FAST_INSTANT_TRADE_PAY);
        AlipayClient alipayClient = getClient();
        String returnUrl = alipayProperties.getReturn_url();
        AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
        // 成功后回调地址
        request.setReturnUrl(returnUrl);
        // 请求体
        request.setBizContent(JSONUtil.toJsonStr(alipayBean));
        AlipayTradePagePayResponse response = alipayClient.pageExecute(request);
        // 订单号
        System.out.println("outTradeNo = " + out_trade_no);
        if (response.isSuccess()) {
            System.out.println("调用成功");
        } else {
            System.out.println("调用失败");
        }


        /**
         *  Runnable command, 执行的方法
         *  long initialDelay, 延迟执行时间
         *  long period 执行周期时间
         *  TimeUnit unit 单位
         */
        scheduledExecutorService.scheduleAtFixedRate(() -> {
            //查询
            queryInfo(alipayClient, out_trade_no);
        }, 10L, 3L, TimeUnit.SECONDS);

        // 一分钟未支付关闭交易订单
        scheduledExecutorService.scheduleAtFixedRate(() -> {
            AlipayTradeCloseRequest alipayTradeCloseRequest = new AlipayTradeCloseRequest();
            AlipayTradeQueryModel queryModel = new AlipayTradeQueryModel();
            // 设置订单编号
            queryModel.setOutTradeNo(out_trade_no);
            alipayTradeCloseRequest.setBizModel(queryModel);
            AlipayTradeCloseResponse alipayTradeCloseResponse = null;
            try {
                alipayTradeCloseResponse = alipayClient.execute(alipayTradeCloseRequest);
            } catch (AlipayApiException e) {
                e.printStackTrace();
            }
            if (alipayTradeCloseResponse.isSuccess()) {
                if ("10000".equals(alipayTradeCloseResponse.getCode())) {
                    System.out.println("已取消支付，订单关闭成功");
                    scheduledExecutorService.shutdown();
                } else System.out.println(alipayTradeCloseResponse.getSubMsg());
                System.out.println("调用成功");
            } else {
                System.out.println("调用失败，" + alipayTradeCloseResponse.getSubMsg() + "，关闭定时任务");
                scheduledExecutorService.shutdown();
            }
        }, 60, 3L, TimeUnit.SECONDS);

        return response.getBody();
    }

    /**
     * 查询订单状态
     *
     * @param out_trade_no 订单号
     */
    @SneakyThrows
    @GetMapping("/queryOredr")
    public String queryOrder(String out_trade_no) {
        AlipayClient alipayClient = getClient();
        AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
        AlipayTradeQueryModel queryModel = new AlipayTradeQueryModel();
        // 设置订单编号来查询
        queryModel.setOutTradeNo(out_trade_no);
        request.setBizModel(queryModel);
        AlipayTradeQueryResponse queryResponse = alipayClient.execute(request);
        String body = queryResponse.getBody();
        if (queryResponse.isSuccess()) {
            // 请求成功
            System.out.println("支付宝交易号       : " + queryResponse.getTradeNo());
            System.out.println("商家订单号         : " + queryResponse.getOutTradeNo());
            System.out.println("买家支付宝账号     : " + queryResponse.getBuyerLogonId());
            System.out.print("交易状态:");
            switch (queryResponse.getTradeStatus()) {
                case "WAIT_BUYER_PAY":
                    System.out.println("交易创建，等待买家付款");
                    break;
                case "TRADE_CLOSED":
                    System.out.println("未付款交易超时关闭，或支付完成后全额退款");
                    break;
                case "TRADE_FINISHED":
                    System.out.println("交易结束，不可退款");
                    break;
                case "TRADE_SUCCESS":
                    System.out.println("交易支付成功");
                    break;
            }
            System.out.println("交易的订单金额     : " + queryResponse.getTotalAmount());
        } else {
            System.err.println(queryResponse.getSubMsg());
        }
        return body;
    }

    /**
     * 关闭交易订单
     *
     * @param out_trade_no 订单号
     */
    @SneakyThrows
    @GetMapping("/closeOredr")
    public String closeOredr(String out_trade_no) {
        String result = "";
        AlipayClient alipayClient = getClient();
        AlipayTradeCloseRequest request = new AlipayTradeCloseRequest();
        AlipayTradeQueryModel queryModel = new AlipayTradeQueryModel();
        // 设置订单编号
        queryModel.setOutTradeNo(out_trade_no);
        request.setBizModel(queryModel);
        AlipayTradeCloseResponse response = alipayClient.execute(request);
        if (response.isSuccess()) {
            if ("10000".equals(response.getCode())) {
                result = "已取消支付，订单关闭成功";
            } else result = response.getSubMsg();
            System.out.println("调用成功");
        } else {
            result = response.getSubMsg();
            System.out.println("调用失败：" + result);
            System.out.println("支付宝交易号       : " + response.getTradeNo());
            System.out.println("商家订单号         : " + response.getOutTradeNo());
        }
        return result;
    }

    /**
     * 退款
     *
     * @param out_trade_no 订单号
     */
    @SneakyThrows
    @PostMapping("/refund")
    public String refund(String out_trade_no) {
        String result = "";
        AlipayClient alipayClient = getClient();
        AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
        AlipayTradeRefundModel model = new AlipayTradeRefundModel();
        // 订单号
        model.setOutTradeNo(out_trade_no);
        // 退款金额
        model.setRefundAmount("30");
        request.setBizModel(model);
        AlipayTradeRefundResponse response = alipayClient.execute(request);
        if (response.isSuccess()) {
            if ("10000".equals(response.getCode())) {
                result = response.getBody();
            } else result = response.getSubMsg();
            System.out.println("调用成功");
        } else {
            System.out.println("退款调用失败，" + response.getSubMsg());
        }
        return result;
    }

    /**
     * 查账单下载
     *
     * @param dateStr 订单日期 yyy-MM-dd
     */
    @SneakyThrows
    @PostMapping("/downLoadTrade")
    public String downLoadTrade(String dateStr) {
        String result = "";
        AlipayClient alipayClient = getClient();
        AlipayDataDataserviceBillDownloadurlQueryRequest request = new AlipayDataDataserviceBillDownloadurlQueryRequest();
        AlipayDataDataserviceBillDownloadurlQueryModel model = new AlipayDataDataserviceBillDownloadurlQueryModel();
        // 订单日期
        model.setBillDate(dateStr);
        /**
         * 账单类型，商户通过接口或商户经开放平台授权后其所属服务商通过接口可以获取以下账单类型，支持：
         trade：商户基于支付宝交易收单的业务账单；
         signcustomer：基于商户支付宝余额收入及支出等资金变动的帐务账单。
         */
        model.setBillType("trade");
        request.setBizModel(model);
        AlipayDataDataserviceBillDownloadurlQueryResponse response = alipayClient.execute(request);
        if (response.isSuccess()) {
            if ("10000".equals(response.getCode())) result = response.getBody();
            else result = response.getSubMsg();
            System.out.println("调用成功");
        } else {
            System.out.println("调用失败");
            result = response.getSubMsg();
        }
        return result;
    }


    @SneakyThrows
    private void queryInfo(AlipayClient alipayClient, String out_trade_no) {
        //设置请求参数
        AlipayTradeQueryRequest queryRequest = new AlipayTradeQueryRequest();
        AlipayTradeQueryModel queryModel = new AlipayTradeQueryModel();
        // 设置订单编号来查询
        queryModel.setOutTradeNo(out_trade_no);
        queryRequest.setBizModel(queryModel);
        AlipayTradeQueryResponse queryResponse = alipayClient.execute(queryRequest);
        if (queryResponse.isSuccess()) {
            // 请求成功
            System.out.println("支付宝交易号       : " + queryResponse.getTradeNo());
            System.out.println("商家订单号         : " + queryResponse.getOutTradeNo());
            System.out.println("买家支付宝账号     : " + queryResponse.getBuyerLogonId());
            System.out.print("交易状态:");
            switch (queryResponse.getTradeStatus()) {
                case "WAIT_BUYER_PAY":
                    System.out.println("交易创建，等待买家付款");
                    break;
                case "TRADE_CLOSED":
                    System.out.println("未付款交易超时关闭，或支付完成后全额退款");
                    // 交易支付成功关闭定时任务
                    scheduledExecutorService.shutdown();
                    break;
                case "TRADE_FINISHED":
                    System.out.println("交易结束，不可退款");
                    break;
                case "TRADE_SUCCESS":
                    System.out.println("交易支付成功");
                    System.out.println("交易支付成功关闭定时任务");
                    // 交易支付成功关闭定时任务
                    scheduledExecutorService.shutdown();
                    break;
            }
            System.out.println("交易的订单金额     : " + queryResponse.getTotalAmount());
        }
//        else {
//            System.err.println(queryResponse.getSubMsg());
//            scheduledExecutorService.shutdown();
//        }
    }


}


